/****************************************************************************
 * Copyright (C) 2009-2010 GGA Software Services LLC
 *
 * This file may be distributed and/or modified under the terms of the
 * GNU Affero General Public License version 3 as published by the Free
 * Software Foundation and appearing in the file LICENSE.GPL included in
 * the packaging of this file.
 *
 * This file is provided AS IS with NO WARRANTY OF ANY KIND, INCLUDING THE
 * WARRANTY OF DESIGN, MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE.
 ***************************************************************************/

if(!window.util)
	util = {};

util.Set = {
	empty: function ()
	{
		return {};
	},

	single: function (item)
	{
		var set = {};
		util.Set.add(set, item);
		return set;
	},

	size: function (set)
	{
		var cnt = 0;
		for(var id in set)
		{
			if(set [id] !== Object.prototype[id])
			{
				cnt++;
			}
		}
		return cnt;
	},

	contains: function (set, v)
	{
		return typeof (set [v]) != "undefined" && set [v] !== Object.prototype[v];
	},

	subset: function (subset, superset)
	{
		for(var id in subset)
		{
			if(subset[id] !== Object.prototype[id])
			{
				if(superset[id] !== subset[id])
				{
					return false;
				}
			}
		}
		return true;
	},

	intersection: function (set1, set2)
	{
		var set = {};
		for(var id in set1)
		{
			if(set1[id] !== Object.prototype[id])
			{
				if(set2[id] === set1[id])
				{
					util.Set.add(set, id);
				}
			}
		}
		return set;
	},

	disjoint: function (set1, set2)
	{
		for(var id in set1)
		{
			if(set1[id] !== Object.prototype[id])
			{
				if(set2[id] === set1[id])
				{
					return false;
				}
			}
		}
		return true;
	},

	eq: function (set1, set2)
	{
		return util.Set.subset(set1, set2) && util.Set.subset(set2, set1);
	},

	each: function (set, func, context)
	{
		for(var v in set)
		{
			if(set [v] !== Object.prototype[v])
			{
				func.call(context, set [v]);
			}
		}
	},

	filter: function (set, func, context)
	{
		var subset = {};
		for(var v in set)
		{
			if(set [v] !== Object.prototype[v])
			{
				if(func.call(context, set [v]))
				{
					subset[set [v]] = set [v];
				}
			}
		}
		return subset;
	},

	pick: function (set)
	{
		for(var v in set)
		{
			if(set [v] !== Object.prototype[v])
			{
				return set [v];
			}
		}
		return null;
	},

	list: function (set)
	{
		var list = [];
		for(var v in set)
		{
			if(set [v] !== Object.prototype[v])
			{
				list.push(set [v]);
			}
		}
		return list;
	},

	add: function (set, item)
	{
		set [item] = item;
	},

	mergeIn: function (set, other)
	{
		util.Set.each(other, function (item)
		{
			util.Set.add(set, item);
		});
	},

	remove: function (set, item)
	{
		var v = set [item];
		delete set [item];
		return v;
	},

	clone: function (other)
	{
		var set = {};
		util.Set.mergeIn(set, other);
		return set;
	},

	fromList: function (list)
	{
		var set = {};
		if(list)
		{
			for(var i = 0; i < list.length; ++i)
			{
				set [list[i] - 0] = list[i] - 0;
			}
		}
		return set;
	},

	keySetInt: function (map)
	{
		var set = {};
		map.each(function (id)
		{
			set [id - 0] = id - 0;
		});
		return set;
	},

	find: function (set, func, context)
	{
		for(var v in set)
		{
			if(set [v] !== Object.prototype[v])
			{
				if(func.call(context, set [v]))
				{
					return v;
				}
			}
		}
		return null;
	}
};
